﻿package network {

	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.events.*;
	import flash.net.Socket;
	import flash.system.Security;
	import flash.text.TextField;
	
	public class ClientSocket extends Sprite {
		private var clientVersion:String;
		private var socket:Socket;
		private var theStage:SeriousGame;
		private var state:String = "";
		private var stringTemp:String = "";
		private var stringTempRest:String = "";
		private var chatMessageExpected:Boolean = false;
		private var lobbyChatMessageExpected:Boolean = false;
		private var messageCompleted:Boolean = false;
		private var incomingPlayers = 0;
		private var numberOfJoinedPlayers : int;
		private var playerJoined : Boolean = false;
		private var userForFeatureTaken : String;

		public function ClientSocket( theStage:SeriousGame ) {
		  socket = new Socket();
		  this.theStage = theStage;
		  
		  socket.addEventListener(Event.CONNECT, onConnect);
		  socket.addEventListener(IOErrorEvent.IO_ERROR, onError);
		}
		
		public function connect(host:String, port:int, clientVersion:String) {
			// Connect to the server
			this.clientVersion = clientVersion;
			this.removeEventListener( Event.ENTER_FRAME, onSocketData );
			//var xml:XMLSocket = new XMLSocket();
			
			//xml.connect(host, port);
			Security.loadPolicyFile("xmlsocket://"+host+":"+port);
			socket.connect(host, port);
			
			
		}
		
		private function onError(event:Event):void {
			this.theStage.connectScreen.connectMC.visible=false;
			this.theStage.connectScreen.output.text = "Couldn't connect with the server (maybe server is offline). Please try again later.";
		}
		
		private function onConnect(event:Event):void {
			
			this.addEventListener( Event.ENTER_FRAME, onSocketData );
			
			// Benutzt der User die aktuelle Version??
			send("handshaking\n");
		}
		
		/**
		 * Zum senden eines Strings an den Server (mit \n abschlie√üen!!)
		 * */
		public function send( str:String ):void {
			if(socket.connected) {
				socket.writeUTFBytes(str);
			 	socket.flush();
			}
		}
		
		private function onSocketData(event:Event ):void {
		  //trace( "Socket received " + socket.bytesAvailable + " byte(s) of data:" );
		  	
			if(socket.bytesAvailable + stringTempRest.length >= 25) {
				
				var string:String = "";
				var string2:String = "";
				var value:String;
				
				/** Servernachrichten einlesen **/
				
				if(!chatMessageExpected && !lobbyChatMessageExpected) {
					if(stringTempRest.length > 0) {
						// den Rest vorne dranh√§ngen und den Rest an Zeichen bis 25 auslesen
						if(stringTempRest.length < 25) {
							string2 = stringTempRest + socket.readUTFBytes(25-stringTempRest.length);
							stringTempRest = "";
						} else {
							string2 = stringTempRest.substr(0, 25);
							if(stringTempRest.length > 25)
								stringTempRest = stringTempRest.substr(25, stringTempRest.length);
							else
								stringTempRest = "";
						}
					} else
						string2 = socket.readUTFBytes(25);
					
					string = string2.substr(0, string2.indexOf("/"));
						
					this.messageCompleted = false;
				} else {
					string = socket.readUTFBytes(socket.bytesAvailable);
					this.stringTemp = this.stringTempRest + this.stringTemp;
					
					var temp:String = stringTemp+string;
					if(temp.indexOf(".__-.qYpq") == -1) {
						// ChatMessage ist noch nicht abgeschlossen ... 
						// ChatMessage abspeichern
						this.stringTemp += string;
						
						this.messageCompleted = false;
					} else {
						// ChatMessage abgeschlossen
						this.stringTemp += string;
						var endIndex:int = stringTemp.indexOf(".__-.qYpq", 0);
						
						// Rest des Strings hinter dem Endstring abschneiden (+9)
						this.stringTempRest = stringTemp.substr(endIndex+9, stringTemp.length);
						
						// die Chatmessage
						string = this.stringTemp.substr(0, endIndex); 
						
						this.stringTemp = "";
						
						this.messageCompleted = true;
					}
				}
				
				
				/** "Statemachine" - behandelt/verarbeitet die weiteren Befehle und Nachrichten des Servers **/
				// die variable "string" enth√§lt die nachricht vom server !
							trace(string);
				
				// Beispiel:
				if(state == "bla") {
					// etwas tun
					
					// state wieder zur√ºcksetzen
					state = "";
					// und servernachricht zur√ºcksetzen
					string = "";
				} else if(state == "handshaking") {
					var cScreen:MovieClip = MovieClip(theStage.getChildByName("connectScreen"));
					var out:TextField = cScreen.output;
					
					if(string == clientVersion) {
						// Client benutzt richtige Version
																	
						//loginScreen.visible = true;
						out.text = "Connected!";
						this.theStage.connectedToServer();
					} else {
						// Falsche Version
						out.text = "You're running an older version of this game. The current version is v" + string + ". Please visit the official website.";
					}
					state="";
				} else if(state == "numberOfPlayersJoinGame"){
					trace("numberOfPlayersJoinGame");
					this.numberOfJoinedPlayers = int(string.split(":")[0]);
					var numberOfPlayers:int = int(string.split(":")[1]);
					this.theStage.setPlayers(new Array(numberOfPlayers));
					state = "playersForJoinGame";
				}else if(state == "playersForJoinGame"){
					trace("playersForJoinGame: " + incomingPlayers);
					trace(this.theStage.getPlayers());
					this.theStage.getPlayers()[incomingPlayers] = new Player();
					Player(this.theStage.getPlayers()[incomingPlayers]).setName(string);
					state = "companyForJoinGame";
				}else if(state == "companyForJoinGame"){
					trace("companyForJoinGame");
					Player(this.theStage.getPlayers()[incomingPlayers]).setCompany(string);
					incomingPlayers++;
					
					
					if(incomingPlayers==this.numberOfJoinedPlayers){
						if(!playerJoined){
							this.theStage.showLobby();
						}else{
							this.theStage.playerJoinedGame(this.theStage.getPlayers()[incomingPlayers-1],this.numberOfJoinedPlayers);
						}
						
						state = "";
					}else{
						state = "playersForJoinGame";
					}
				}else if(state == "playerHowIsReady"){
					this.theStage.playerIsReady(string);
					state = "";
				}else if(state == "playerHowIsNotReady"){
					this.theStage.playerIsNotReady(string);
					state = "";
				}else if(state == "settingBombs"){
					if(string == "setBombFinished") {
						state = "";
					} else {
						var varArray:Array = string.split(":");
						var xVar:int = parseInt(varArray[0]);
						var yVar:int = parseInt(varArray[1]);
						this.theStage.putBomb(xVar, yVar);
					}
				}else if(state == "move"){
					trace("move");
					var stringArray:Array = string.split(":");
					var newPositionX:int = parseInt(stringArray[0]);
					var newPositionY:int = parseInt(stringArray[1]);
					var newRotation:int = parseInt(stringArray[2]);
					var bombPos:int = parseInt(stringArray[3]);
					trace("bombPos in cS: "+bombPos);
					if(!this.theStage.getRunner()) {
						this.theStage.doMove(newPositionX, newPositionY, newRotation, bombPos);
					}
					state = "";
				}else if(state == "defuse"){
					trace(".....receiving defuse");
					if(this.theStage.getRunner()) {
						this.theStage.removeMoveListener();
						trace("...ist runner: remove Listener");
					}
					var defuseNum:int = parseInt(string);
					trace("received defuseNumber: "+defuseNum);
					this.theStage.doDefuse(defuseNum);
					state = "";
				}else if(state== "userForFeatureTaken"){
					this.userForFeatureTaken = string;
					state = "featureForFeatureTaken";
				}else if(state== "defuseBombNumber"){
					var num:int = parseInt(string);
					if(this.theStage.getDefuser() && num != -1) {
						this.theStage.defuse(num);
					}
					state = "";
				}else if(state == "featureForFeatureTaken"){
					this.theStage.featureTaken(this.userForFeatureTaken,string);
					this.theStage.deactivateCheckBoxes(string);
					state = "";
				}else if(state == "userForFeatureUntaken"){
					this.userForFeatureTaken = string;
					state = "featureForFeatureUntaken";
				}else if(state == "featureForFeatureUntaken"){
					this.theStage.featureUntaken(this.userForFeatureTaken,string);
					this.theStage.activateCheckBoxes(string);
					state = "";
				}else if(state == "gameOver"){
					if(string == "unsuccessful"){
						this.theStage.cleanupGame(string);
					}else{
						state = "waitingForPoints";
					}
				}else if(state == "waitingForPoints"){
					this.theStage.setPoints(int(string));
					this.theStage.cleanupGame("successful");
					state == "";
				}
				
				if(string == "tick") {
					this.theStage.updateGameTimer();
				} else if(string == "bla") {
					state = "bla";
				} else if(string == "handshaking") {
					state = "handshaking";
				} else if(string == "gameJoined") {
					state = "numberOfPlayersJoinGame";
				} else if(string == "playerJoined"){
					state = "playersForJoinGame";
					this.numberOfJoinedPlayers++;
					this.playerJoined = true;
					
				} else if(string == "ready"){
					state = "playerHowIsReady";
				}else if(string == "unready"){
					state = "playerHowIsNotReady";
				}else if(string == "loggedIn"){
					this.theStage.playerLoggedIn();
				}else if(string == "allReady"){
					this.theStage.playersAllReady();
				} else if(string == "startGame") {
					this.theStage.initLevel();
				} else if(string == "setBomb") {
					state = "settingBombs";
				} else if(string == "move") {
					state = "move";
				} else if(string == "defuse") {
					trace("defuseState");
					state = "defuse";
				} else if(string == "defused") {
					if(this.theStage.getRunner()) {
						this.theStage.addMoveListener();
					}
				} else if(string == "featureTaken"){
					state = "userForFeatureTaken";
					this.userForFeatureTaken = "";
				} else if(string == "featureUntaken"){
					state = "userForFeatureUntaken";
					this.userForFeatureTaken = "";
				}else if(string == "playerExists"){
					cScreen = MovieClip(theStage.getChildByName("registerScreen"));
					out = cScreen.output;
					out.text = "Player name already exits";
				}else if(string == "featureNotSelectable"){
					this.theStage.featureNotSelectable();
				}else if(string == "gameOver"){
					state = "gameOver";
				}else if(string == "quizTimeStarted"){
					this.theStage.quizTimeStarted();
				}else if(string == "quizTimeEnded"){
					this.theStage.quizTimeEnded();
				}
				
			}
		}

		
	}
}
